import * as Cesium from '@cesiumjs';
import {G3xObjBase,G3vObj} from "@g3xObjBase"
import * as g3xUtils from "@g3x/utils";
import {
  autorun,
  reaction,
  intercept,
  extendObservable,
  computed
} from 'mobx';

import createMaterials from "./materials";
import initSchema from "./schema";

import uniquePositions from "../uniquePositions"

const arcTypeMap = {
  default: Cesium.ArcType.NONE,
  NONE: Cesium.ArcType.NONE,
  GEODESIC: Cesium.ArcType.GEODESIC,
  RHUMB: Cesium.ArcType.RHUMB
};

function getMaterial(material,t){
  let m = material[t].material;
  if(!m){
    material[t].material = (m = createMaterials(t))
  }
  return m;
}

/**
 *
 */
class G3xPolyline extends G3vObj {
  constructor(viewer, options) {

    super(viewer, options);
    this._pointsColor = [1, 1, 0, 0.95];
    // g3xUtils.g3x_defineReadonly(this, "viewer", viewer)
    this.init()
  }

  init() {
    const _this = this;
    const {
      disposers,
      viewer
    } = _this;

    function createPrimitive() {
      var positions = uniquePositions(_this.positions);
      if (positions.length <= 1) {
        return undefined;
      }
      var cartesians = positions.map(function(p) {
        var _Cesium$Cartesian = Cesium.Cartesian3;
        return _Cesium$Cartesian.fromRadians.apply(_Cesium$Cartesian, p);
      });

      if (_this.loop && positions.length >= 3) {
        cartesians.push(cartesians[0]);
        // 如果只首尾相连，导致的问题时width比较大时，首位相连的线段会有一个小缝
        cartesians.push(cartesians[1]);
      }

      const _material = getMaterial(_this.material,_this.material.type);
      const material = _material.material;

      var appearance = new Cesium.PolylineMaterialAppearance({
        material,
        renderState: {
          depthTest: {
            enabled: _this.depthTest
            // depthMask: this.depthMask, 设置无效，Appearance内部会强行设置
          }
          // translucent: this.forceTranslucent, // 这里的设置同样无效，因为material强制控制是否透明
        }
      });
      appearance.renderState.depthMask = false;

      var primitive = new Cesium.Primitive({
        geometryInstances: new Cesium.GeometryInstance({
          geometry: new Cesium.PolylineGeometry({
            positions: cartesians,
            width: _this.width,
            vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
            // arcType: Cesium.ArcType.RHUMB, // 会导致z轴忽隐忽现
            arcType: arcTypeMap[_this.arcType]
          }),
          id: _this
        }),
        appearance: appearance,
        asynchronous: false, // 防止闪烁
        allowPicking: _this.allowPicking, // 不允许拾取
        compressVertices: false // 提升效率
      });

      var ou = primitive.update;
      var that = _this;
      primitive.update = function(frameState) {
        ou.call(this, frameState);
        this._colorCommands.forEach(function(e) {
          // e.pass = Cesium.Pass.OVERLAY;
          that.forcePass && (e.pass = that.forcePass);
        });
      };

      return primitive;
    };

    function createGroundPrimitive() {
      var positions = uniquePositions(_this.positions);
      if (positions.length <= 1) {
        return undefined;
      }
      var cartesians = positions.map(function(p) {
        var _Cesium$Cartesian2;
        return (_Cesium$Cartesian2 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian2, p);
      });

      if (_this.loop && positions.length >= 3) {
        cartesians.push(cartesians[0]);
        // 如果只首尾相连，导致的问题时width比较大时，首位相连的线段会有一个小缝
        cartesians.push(cartesians[1]);
      }

      const material = getMaterial(_this.material,_this.material.type);

      var groundPrimitive = new Cesium.GroundPolylinePrimitive({
        geometryInstances: new Cesium.GeometryInstance({
          geometry: new Cesium.GroundPolylineGeometry({
            positions: cartesians,
            width: _this.width,
            vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
            // arcType: Cesium.ArcType.RHUMB, // 会导致z轴忽隐忽现
            arcType: arcTypeMap[_this.arcType]
          }),
          id: _this
        }),
        appearance: new Cesium.PolylineMaterialAppearance({
          material,
          renderState: {
            depthTest: {
              enabled: _this.depthTest
              // depthMask: this.depthMask,
            }
            // translucent: this.forceTranslucent, // 这里的设置同样无效，因为material强制控制是否透明
          }
        }),
        asynchronous: false, // 防止闪烁
        allowPicking: _this.allowPicking, // 不允许拾取
        compressVertices: false // 提升效率
      });

      return groundPrimitive;
    };

    function createPolyline() {
      var positions = _this.positions;
      _this._primitive && viewer.scene.primitives.remove(_this._primitive);
      _this._primitive = undefined;
      _this._groundPrimitive && viewer.scene.groundPrimitives.remove(_this._groundPrimitive);
      _this._groundPrimitive = undefined;

      if (positions.length >= 2) {
        if (!_this.ground) {
          _this._primitive = createPrimitive();
          _this._primitive && viewer.scene.primitives.add(_this._primitive);
        } else {
          _this._groundPrimitive = createGroundPrimitive();
          _this._groundPrimitive && viewer.scene.groundPrimitives.add(_this
            ._groundPrimitive);
        }
      }
    };

    function updatePolyline() {
      const {
        _primitive,
        _groundPrimitive,
        material,
        show
      } = _this;

      _primitive && (_primitive.show = show);
      _groundPrimitive && (_groundPrimitive.show = show);

      const _material = getMaterial(material,material.type);

      // var czmMaterial = material[material.type] materials.get(material.type).material;
      _primitive && (_primitive.appearance.material = _material.material);
      _groundPrimitive && (_groundPrimitive.appearance.material = _material.material);
    };

    function updateBoundingSphere() {
      var positions = _this.positions;
      var cartesians = positions.map(function(p) {
        var _Cesium$Cartesian3;
        return (_Cesium$Cartesian3 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian3, p);
      });
      _this._boundingSphere = Cesium.BoundingSphere.fromPoints(cartesians, _this._boundingSphere);
    };

    disposers.push(reaction(() => {
      const positions = _this.positions.map(e => [...e]);
      const {
        loop,
        ground,
        depthTest,
        arcType,
        width,
        allowPicking
      } = _this;
      return {
        positions,
        loop,
        ground,
        depthTest,
        arcType,
        width,
        allowPicking
      };
    }, () => {
      createPolyline();
      updateBoundingSphere();
      updatePolyline();
    }));

    disposers.push(autorun(updatePolyline));
  }
}

(0, initSchema)(G3xPolyline);

export default G3xPolyline;
